package com.yuqih.common.service.view.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;

import com.yuqih.common.service.view.ITreeViewBuilder;
import com.yuqih.common.service.view.IViewBuildRegistry;
import com.yuqih.common.service.view.IViewBuilder;
import com.yuqih.common.service.view.IViewService;

@Service
public class ViewService implements IViewService, IViewBuildRegistry {

	private final Log logger = LogFactory.getLog(getClass());

	private final Map<Class<?>, Map<String, IViewBuilder<?>>> mapping = new HashMap<Class<?>, Map<String, IViewBuilder<?>>>();
	private final Map<Class<?>, Map<String, ITreeViewBuilder<?>>> treeMapping = new HashMap<Class<?>, Map<String, ITreeViewBuilder<?>>>();

	@Override
	public synchronized <T> void register(Class<T> type, String viewName, IViewBuilder<T> builder) {
		Map<String, IViewBuilder<?>> viewMapping = mapping.get(type);
		if (viewMapping == null) {
			viewMapping = new HashMap<String, IViewBuilder<?>>();
			mapping.put(type, viewMapping);
		}
		IViewBuilder<?> replaced = viewMapping.put(viewName, builder);
		if (replaced != null) {
			logger.warn("视图定义[" + type.getName() + " - " + viewName + "]重复");
		}

	}

	@Override
	public synchronized <T> void register(Class<T> type, String viewName, ITreeViewBuilder<T> builder) {
		Map<String, ITreeViewBuilder<?>> viewMapping = treeMapping.get(type);
		if (viewMapping == null) {
			viewMapping = new HashMap<String, ITreeViewBuilder<?>>();
			treeMapping.put(type, viewMapping);
		}
		ITreeViewBuilder<?> replaced = viewMapping.put(viewName, builder);
		if (replaced != null) {
			logger.warn("树视图定义[" + type.getName() + " - " + viewName + "]重复");
		}

	}

	@Override
	public <T> Object build(Class<T> type, String viewName, T source) {
		IViewBuilder<T> builder = findBuilder(type, viewName);

		if (source == null) {
			return null;
		}
		return builder.build(source);
	}

	@Override
	public <T> List<Object> buildList(Class<T> type, String viewName, List<T> sourceList) {

		if (sourceList == null) {
			return null;
		} else if (sourceList.isEmpty()) {
			return Collections.emptyList();
		}

		if (StringUtils.startsWith(viewName, "tree:")) {
			viewName = StringUtils.removeStart(viewName, "tree:");
			return buildTree(type, viewName, sourceList);
		}

		IViewBuilder<T> builder = findBuilder(type, viewName);

		List<Object> list = new ArrayList<Object>();
		for (T source : sourceList) {
			Object result = builder.build(source);
			if (result != null) {
				list.add(result);
			}
		}

		return list;
	}

	@Override
	public <T> List<Object> buildTree(Class<T> type, String viewName, List<T> sourceList) {
		if (sourceList == null) {
			return null;
		} else if (sourceList.isEmpty()) {
			return Collections.emptyList();
		}

		ITreeViewBuilder<T> builder = findTreeBuilder(type, viewName);

		return builder.build(sourceList);
	}

	@SuppressWarnings("unchecked")
	private <T> IViewBuilder<T> findBuilder(Class<T> type, String viewName) {
		if (type == null || viewName == null) {
			throw new NullPointerException();
		}

		Map<String, IViewBuilder<?>> viewMapping = mapping.get(type);
		if (viewMapping == null) {
			throw new IllegalArgumentException(type.getName() + "类型没有注册任何视图构建器");
		}

		IViewBuilder<?> builder = viewMapping.get(viewName);
		if (builder == null) {
			throw new IllegalArgumentException(type.getName() + "类型没有注册视图构建器[" + viewName + "]");
		}

		return (IViewBuilder<T>) builder;
	}

	@SuppressWarnings("unchecked")
	private <T> ITreeViewBuilder<T> findTreeBuilder(Class<T> type, String viewName) {
		if (type == null || viewName == null) {
			throw new NullPointerException();
		}

		Map<String, ITreeViewBuilder<?>> viewMapping = treeMapping.get(type);
		if (viewMapping == null) {
			throw new IllegalArgumentException(type.getName() + "类型没有注册任何视图构建器");
		}

		ITreeViewBuilder<?> builder = viewMapping.get(viewName);
		if (builder == null) {
			throw new IllegalArgumentException(type.getName() + "类型没有注册视图构建器[" + viewName + "]");
		}

		return (ITreeViewBuilder<T>) builder;
	}

}
